using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using umbraco;
using umbraco.presentation.xslt.Exslt;
using UmbracoXsltEditor.Umbraco.FileService;

namespace UmbracoXsltEditor.Util
{
    public static class UmbracoHelper
    {
        public static byte[] GetUmbracoXml(string username, string password)
        {
            fileService fservice = new fileService();

            byte[] umbracoFile = fservice.DownloadFile("data", "umbraco.config", username, password);

            return umbracoFile;

        }

        public static string[] GetXsltFileList(string username, string password)
        {
            fileService fservice = new fileService();

            string[] files = fservice.GetFilesList("xslt", username, password);

            return files;
        }

        public static byte[] GetXsltFile(string username, string password, string fileName)
        {
            fileService fservice = new fileService();

            byte[] xsltFile = fservice.DownloadFile("xslt", fileName, username, password);

            return xsltFile;
        }

        public static Dictionary<string, string> GetNodeTree(string xml)
        {
            Dictionary<string, string> list = new Dictionary<string, string>();
            
            //Parse the XML
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);

            XmlElement elem = doc.DocumentElement;
            XmlNodeList nodes = elem.SelectNodes("child::node");

            //Traverse the tree and fill the dictionary
            TraverseXml(nodes, list, 0);

            return list;
        }

        private static void TraverseXml(XmlNodeList nodes, Dictionary<string, string> list, int currentLevel)
        {
            for(int i=0; i<nodes.Count; i++ )
            {
                XmlNodeType type = nodes[i].NodeType;
                if(type == XmlNodeType.Element)
                {
                    string name = nodes[i].Attributes["nodeName"].Value;
                    name = name.PadLeft(currentLevel+name.Length, '-');
                    string id = nodes[i].Attributes["id"].Value;
                    //id attributes are unique to a node, nodeName is not so id needs to be the key
                    list.Add(id, name);
                }

                //Loop children
                currentLevel++;
                XmlNodeList children = nodes[i].SelectNodes("child::node");
                TraverseXml(children, list, currentLevel);
                currentLevel--;

            }

        }

        public static string Transform(string xslt, string xml, string currentPageId)
        {
            TextWriter tw = new StringWriter();

            try
            {
                //XmlReader settings
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.ProhibitDtd = false;

                //Set up the XML reader
                byte[] memXml = Encoding.UTF8.GetBytes(xml);
                MemoryStream xmlStream = new MemoryStream(memXml);
                MemoryStream xmlStream2 = new MemoryStream(memXml);
                XmlReader xmlReader = XmlReader.Create(xmlStream, settings);
                XmlReader xmlReader2 = XmlReader.Create(xmlStream2, settings);
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlReader2);
                XPathNavigator xmlNav = xmlDoc.CreateNavigator();
                xmlNav.MoveToId(currentPageId);
                

                //Set up the XSLT reader
                byte[] memXslt = Encoding.UTF8.GetBytes(xslt);
                MemoryStream xsltStream = new MemoryStream(memXslt);
                XmlReader xsltReader = XmlReader.Create(xsltStream, settings);

                //Set up the extensions
                XsltArgumentList xslArgs = new XsltArgumentList();
                xslArgs.AddExtensionObject("urn:Exslt.ExsltCommon", new ExsltCommon());
                xslArgs.AddExtensionObject("urn:Exslt.ExsltDatesAndTimes", new ExsltDatesAndTimes());
                xslArgs.AddExtensionObject("urn:Exslt.ExsltMath", new ExsltMath());
                xslArgs.AddExtensionObject("urn:Exslt.ExsltRegularExpressions", new ExsltRegularExpressions());
                xslArgs.AddExtensionObject("urn:Exslt.ExsltStrings", new ExsltStrings());
                xslArgs.AddExtensionObject("urn:Exslt.ExsltSets", new ExsltSets());
                library lib = new library();
                xslArgs.AddExtensionObject("urn:umbraco.library", lib);
                xslArgs.AddParam("currentPage", string.Empty, xmlNav.Select("."));


                //Create/Perform the transform
                XslCompiledTransform result = new XslCompiledTransform();
                result.Load(xsltReader);
                result.Transform(xmlReader, xslArgs, tw);
            }
            catch (Exception ex)
            {
                //Catch all the exceptions, including inner
                MessageBox.Show(ex.Message.ToString(), "Transform Exception");
                Exception Inner = ex.InnerException;
                while (Inner != null)
                {
                    MessageBox.Show(Inner.Message.ToString(), "Inner Exception");
                    Inner = Inner.InnerException;
                }
            }

            return tw.ToString();
        }
    }
}
